﻿using System;
using System.Collections.Generic;
using Gaming;
using Layers.Tests;

namespace Gaming.Tests
{

    public class GeneratorTest:TestBase
    {
        public ulong Cases;

        DateTime _start;

        public override void All()
        {
            TestCombinations();
            TestGeneratorBoard();
 
        }

        public void TestGenerator()
        {
            HoldemTable table = HoldemTable.FromPlayersAndVisibles(2, 0);

            TableGenerator tableGen = new TableGenerator(table);

            tableGen.TableGenerated += new EventHandler<TableEventArgs>(tableGen_TableGenerated);

            if (false)
                tableGen.Constraints =
                new CardConstraint[]
            {
                new TableConstraint(table.HoleCards(0), 
                    new CardSetList(
                        CardSet.Parse("AsQh"),
                        CardSet.Parse("Td2s"
                        )),
                    null)
            };

            _start = DateTime.Now;
            WriteLine("Enumerating all TIME={0}", _start);

            Cases = 0;
            tableGen.Enumerate();

            double time = GetTime();
            WriteLine("Done {0} cases Spent={1:F2}s {2:F0} case/sec", Cases, time, Cases/time);
        }

        public void TestGeneratorBoard()
        {

            HoldemTable table = HoldemTable.FromPlayersAndVisibles(2,3);

            table.HoleCards(0).SetKnown(CardSetList.Parse("AsQs", "KdKs"));

            table.VisibleBoardCards.SetKnown(CardSetList.Parse("AsKdQh"));

            table.InvisibleBoardCards.SetRandom();

            TableGenerator gen = new TableGenerator(table);
            gen.TableGenerated += new EventHandler<TableEventArgs>(TestGeneratorBoard_Generated);

            _start = DateTime.Now;
            Cases = 0;
            gen.Enumerate();

            double time = GetTime();
            WriteLine("Done {0} cases Spent={1:F2}s {2:F0} case/sec Iterations {3}", Cases, time, Cases/time,gen.Iteration );
        }

        void TestGeneratorBoard_Generated(object sender, TableEventArgs e)
        {
            if (false)
            {
                TableGenerator TG = sender as TableGenerator;
                Console.WriteLine(TG.Table.ToString());
            }

            Cases++;
        }

        public void TestCombinations()
        {
            object[,] combs = new object[,]
            {
                {"AsKsQsJsTs", HandType.RoyalFlush},
                {"KsQsJsTs9s", HandType.StraightFlush},
                {"KsQhJsTs9s", HandType.Straight},
                {"KhAh9hTh8h", HandType.Flush},
                {"KsKhKdKc8h", HandType.Care}, // first
                {"KsKhKdKcAs", HandType.Care}, // last
                {"KsKhKdQc8h", HandType.Three}, // first
                {"AsKsKhKd8h", HandType.Three}, // middle
                {"As2s2h2d8h", HandType.Three}, // last
                {"KsKh8dQcQh", HandType.TwoPair}, // first+middle
                {"KsKhQdJcJh", HandType.TwoPair}, // first+last
                {"KsKhKdJcJd", HandType.FullHouse}, // 3+2
                {"KsKhKdAcAd", HandType.FullHouse}, // 2+3

                {"KsQhJsTs8h", HandType.Kicker},
            };

            for (int j = 0; j < combs.Length/2; j++)
            {
                string[] str = new string[2];
                
                str[0] = (string)combs[j, 0];
                str[1] = "";
                
                // make reversion
                for (int k = 0; k <= 4; k++)
                {
                    string tmp = str[0].Substring(2 * k, 2);
                    str[1] = tmp + str[1];
                }
                int type = (int)combs[j, 1];
                for (int rev = 0; rev < 1; rev++)
                {
                    CardSet cs = CardSet.Parse(str[rev]);
                    Hand comb = Hand.From5Cards(cs);
                    Write("{0} parsed as {1} and evaluated as {2}",
                        str[rev], cs.ToString(), comb);
                    if (comb.Type != type)
                        Write(" instead of correct {0}",
                            Hand.CombName(type));
                    WriteLine("");
                }
            }
        }

        double GetTime()
        {
            double time = (DateTime.Now.Subtract(_start)).TotalSeconds;
            return time;
        }

        void tableGen_TableGenerated(object sender, TableEventArgs e)
        {
            TableGenerator TG = sender as TableGenerator;
            Console.WriteLine(TG.Table.ToString());
            Cases++;
            if (Cases % 1000000 == 0)
            {
                double time = GetTime();
                ulong iter = TG.Iteration;
                Console.WriteLine("DBG: Case {0} {1:F4}/s Iteration {2} {3:F4}/s", Cases,Cases/time,iter,iter/time);

                if (false)
                {
                    Console.Write(TG.Table.ToString());
                    CardSet cs = TG.Table.GetCardSet(4, 5, true);
                    Console.Write("         " + cs.ToString());
                    Hand comb = Hand.From5Cards(cs);
                    Console.WriteLine(" ==>  " + comb.ToString());
                }
            }
        }
    }
}